#include "stdafx.h"
#include "AnimView.h"

#include <ctime>

#include "GlobalAppData.h"

#include "Camera.h"
#include "Scene.h"
#include "Node.h"
#include "ModelNode.h"

#include "SceneLoader.h"
#include "WorldData.h"

#include "DeferredPipeline.h"

#include "Graphics.h"
#include "RenderingSystem.h"
#include "MeshInstance.h"
#include "Material.h"
#include "Light.h"
#include "LoadTexture.h"

#include "PhysicsSystem.h"

//debug
#include "CollisionData.h"
#include "CollisionDetection.h"
#include "PhysicsPrimitives.h"

//gui
#include "Window.h"
#include "OnOffButton.h"

#include "RenderSettingsGui.h"

#include "NodeUtil.h"

using namespace ani;

void AnimView::init( mscene::Scene * scene, mgfx::RenderingSystem * rendSys, mphys::PhysicsSystem * physSys )
{
	View::load();
	mCameraStrafing = false;
	mCameraRotating = false;
	
	mTotalTime = 0.0f;

	mScene = scene;
	mRenderSystem = rendSys;
	mPhysicsSystem = physSys;

	float screenAspect = (float)mcore::GlobalAppData::Instance.ScreenWidth / (float)mcore::GlobalAppData::Instance.ScreenHeight;
	mCamera = &mScene->getCamera();
	//mCamera->walk(-230);
	mCamera->setLens(0.25f * PI, screenAspect, 5.0f, 1500.0f);
	mRenderSystem->setProjMatrix(mCamera->proj());

	initGui();
}

void AnimView::update(float dt)
{ 
	static float SMALL_DT = 0.0001f;
	if(mTotalTime == 0.0f)
		dt = SMALL_DT;
	mTotalTime += dt;

	//if(mPhysicsSystem->DebugFirstCollFound == false)
	//{
		//mPhysicsSystem->update(dt);
	//}

	mScene->update(dt);
	
	mRenderSystem->update(dt);
}


void AnimView::unload()
{
	SAFE_DELETE(mRenderSettingsGui);

	SAFE_DELETE(mScene);
	SAFE_DELETE(mPhysicsSystem);
	SAFE_DELETE(mRenderSystem);

	View::unload();
}


void AnimView::draw()
{
	mRenderSystem->setViewMatrix(mCamera->view());
	mRenderSystem->setEyePosition(mCamera->position());
	mRenderSystem->setViewFrustum(mCamera->Frustum_);
	mgfx::DeferredPipeline::get().render(mRenderSystem->Data, mRenderSystem->Settings);

	mGui->draw();
}

bool AnimView::onWindowMessage(UINT msg, WPARAM wParam, LPARAM lParam)
{

	sendInputToGUI(msg, wParam, lParam);

	switch( msg )
	{
	case WM_MOUSEMOVE:
		{
			static bool firstTime = true;
			int mousePosX = LOWORD(lParam);
			int mousePosY = HIWORD(lParam);
			if(firstTime)
			{
				firstTime = false;
			}
			else
			{
				int diffY = mPrevMousePosY - mousePosY;
				int diffX = mPrevMousePosX - mousePosX;
				if(diffY != 0 || diffX != 0)
				{
					if(mCameraStrafing)
					{
						mCamera->strafe(diffX * 0.6f);
						mCamera->moveVertically(-diffY * 0.6f);
					}
					else if(mCameraRotating)
					{
						mCamera->pitch(float(-diffY) * 0.003f);
						mCamera->rotateY(float(-diffX) * 0.003f);
					}
					//mScene->mouseMove(diffX, diffY);
				}

			}
			mPrevMousePosX = mousePosX;
			mPrevMousePosY = mousePosY;
			return true;
		}
		break;

	case WM_MBUTTONDOWN:
		mCameraStrafing = true;
		break;

	case WM_MBUTTONUP:
		mCameraStrafing = false;
		break;

	case WM_RBUTTONDOWN:
		mCameraRotating = true;
		break;

	case WM_RBUTTONUP:
		mCameraRotating = false;
		break;

	case WM_MOUSEWHEEL:
		{
			float delta = GET_WHEEL_DELTA_WPARAM(wParam);
			mCamera->walk(delta * 0.4f);
		}
		break;

	case WM_KEYDOWN:
		{

			return mScene->keyEvent(util::KEY_DOWN, wParam, lParam);
		}
		break;

	case WM_KEYUP:
		{
			return mScene->keyEvent(util::KEY_UP, wParam, lParam);
		}
		break;
	}
	return false;
}

void AnimView::initGui()
{
	mRenderSettingsGui = new medit::RenderSettingsGui(&mRenderSystem->Settings);
	mGui->addChild(*mRenderSettingsGui->GuiWindow);
}
